package com.deimos.tests;

import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.llom.util.AXIOMUtil;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.vast.ows.OWSException;
import org.vast.ows.sps.GetStatusResponse;
import org.vast.ows.sps.ReserveResponse;
import org.vast.ows.sps.SPSUtils;
import org.vast.ows.sps.StatusReport;
import org.vast.ows.sps.StatusReport.RequestStatus;
import org.vast.ows.sps.StatusReport.TaskStatus;
import org.vast.xml.DOMHelper;

import com.deimos.HMA;
import com.deimos.UtilsDeimos;
import com.deimos.dataBase.TaskController;

public class Reserve {

    private static HMA hma = new HMA();
    SPSUtils utils = new SPSUtils();
    static String taskId = null;
    private String DATE_FORMAT_HMA = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private SimpleDateFormat sdf_hma = new SimpleDateFormat(DATE_FORMAT_HMA);

    @BeforeClass
    public static void init() {
	TaskController taskController = new TaskController();
	taskController.createTables(false);
    }

    @Test
    public void Reserve_Syn_Feasible_Incorrect_Expiration() throws Exception {
	try {
	    OMElement request, response;
	    request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Incorrect_Expiration_Request.xml"));
	    response = hma.Reserve(request);

	    StatusReport report = UtilsDeimos.readParams(response.toString()).getReport();
	    if (report.getDescription().contains(" is in use by the task ")) {
		taskId = report.getDescription().split(" is in use by the task ")[1];
		cancel_is_in_use();
		taskId = null;
		Reserve_Syn_Feasible_Incorrect_Expiration();
	    }

	    if (taskId == null) {
		taskId = UtilsDeimos.readParams(response.toString()).getReport().getTaskID();
	    }
	    
	} catch (OWSException ex) {
	    assertTrue(ex.getMessage().contains("The expiration time is not a point in time in the future"));
	}
    }

    @Test
    public void Reserve_Syn_Feasible_Step() throws Exception {
	OMElement request, response;
	request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Step_1_Expiration_Over_Max_Request.xml").replace("RESERVETIME", this.sdf_hma.format(new Date().getTime() + 20000)));
	Thread.sleep(20000);
	response = hma.Reserve(request);

	StatusReport report = UtilsDeimos.readParams(response.toString()).getReport();
	if (report.getDescription().contains(" is in use by the task ")) {
	    taskId = report.getDescription().split(" is in use by the task ")[1];
	    cancel_is_in_use();
	    taskId = null;
	    Reserve_Syn_Feasible_Step();
	}

	if (taskId == null) {
	    
	    InputStream is = new ByteArrayInputStream(response.toString().getBytes());
	    DOMHelper domResponse = new DOMHelper(is, false);
	    StatusReport status = ((ReserveResponse) utils.readXMLResponse(domResponse, domResponse.getRootElement(), "SPS", "ReserveResponse", "2.0")).getReport();
	    assertTrue(status.getRequestStatus() == RequestStatus.Accepted && status.getTaskStatus() == TaskStatus.Reserved);
	    Reserve_Syn_Feasible_Incorrect_Expiration_Step_2();
	    Reserve_Syn_Feasible_Incorrect_Expiration_Step_3();
	    Reserve_Syn_Feasible_Incorrect_Expiration_Step_4();
	    taskId = UtilsDeimos.readParams(response.toString()).getReport().getTaskID();
	}
    }

    public void Reserve_Syn_Feasible_Incorrect_Expiration_Step_2() throws Exception {
	OMElement request, response;
	request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Step_2_Sensor_In_Use_Request.xml"));
	response = hma.Reserve(request);

	if (taskId == null) {
	    taskId = UtilsDeimos.readParams(response.toString()).getReport().getTaskID();
	    InputStream is = new ByteArrayInputStream(response.toString().getBytes());
	    DOMHelper domResponse = new DOMHelper(is, false);
	    StatusReport status = ((ReserveResponse) utils.readXMLResponse(domResponse, domResponse.getRootElement(), "SPS", "ReserveResponse", "2.0")).getReport();
	    assertTrue(status.getRequestStatus() == RequestStatus.Rejected && status.getDescription().contains(" is in use by the task "));
	    cancel_is_in_use();
	}
    }

    public void Reserve_Syn_Feasible_Incorrect_Expiration_Step_3() throws Exception {
	OMElement request, response;
	request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Step_3_GetStatus_Request.xml").replace("TASKID", taskId));
	response = hma.GetStatus(request);

	if (taskId == null) {
	    InputStream is = new ByteArrayInputStream(response.toString().getBytes());
	    DOMHelper domResponse = new DOMHelper(is, false);
	    StatusReport status = ((GetStatusResponse) utils.readXMLResponse(domResponse, domResponse.getRootElement(), "SPS", "GetStatusResponse", "2.0")).getReportList().get(0);
	    assertTrue(status.getTaskStatus() == TaskStatus.Expired);
	}
    }

    public void Reserve_Syn_Feasible_Incorrect_Expiration_Step_4() throws Exception {
	OMElement request, response;
	request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Step_4_Reserve_Request.xml"));
	response = hma.Reserve(request);

	if (taskId == null) {
	    taskId = UtilsDeimos.readParams(response.toString()).getReport().getTaskID();
	    InputStream is = new ByteArrayInputStream(response.toString().getBytes());
	    DOMHelper domResponse = new DOMHelper(is, false);
	    StatusReport status = ((ReserveResponse) utils.readXMLResponse(domResponse, domResponse.getRootElement(), "SPS", "ReserveResponse", "2.0")).getReport();
	    assertTrue(status.getRequestStatus() == RequestStatus.Accepted && status.getTaskStatus() == TaskStatus.Reserved);
	    cancel_is_in_use();
	}
    }

    @After
    public void cancel_is_in_use() throws Exception {
	OMElement request;
	if (taskId == null)
	    return;
	request = AXIOMUtil.stringToOM(AllTests.readTest(AllTests.test_dir + "Reserve_Syn_Feasible_Step_5_Cancel_Request.xml").replace("TASKID", taskId));
	hma.Cancel(request);
    }
}
